package com.fowo.api.datainterface.service.impl.implCore;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.fowo.api.datainterface.aspect.BaseAspect;
import com.fowo.api.datainterface.constants.Constants;
import com.fowo.api.datainterface.constants.DataTypeKind;
import com.fowo.api.datainterface.constants.RequestMethodKind;
import com.fowo.api.datainterface.model.DataContextModel;
import com.fowo.api.datainterface.service.serviceCore.BaseInvokeService;
import com.fowo.api.datainterface.util.Common;
import com.fowo.api.datainterface.util.JScriptUtil;
import com.fowo.api.datainterface.util.JsonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;

@Service
@Slf4j
@DS("ds24")
@RequiredArgsConstructor
public class USPSServiceImpl implements BaseInvokeService {

    private final Common common;

    private volatile BaseAspect baseAspect;

    public synchronized BaseAspect getBaseAspect(String type) {
        return ObjUtil.isEmpty(baseAspect) ? new BaseAspect(type) : baseAspect;
    }
    private final JScriptUtil jScriptUtil;

    @Override
    public DataTypeKind getType() {
        return DataTypeKind.USPS;
    }

   //直接获取
    @Override
    public JSONObject getAuth(DataContextModel.DatainterfaceAuthorityModel invoke) {
        Long timeStamp = DateUtil.current();
        String clientId = common.getAuthoritySimpleFactory(invoke, Constants.USPS_CLIENT_ID);
        String clientSecret = common.getAuthoritySimpleFactory(invoke, Constants.USPS_CLIENT_SECRET);
        String grantType = common.getAuthoritySimpleFactory(invoke, Constants.USPS_GRANT_TYPE);
        String token_url = common.getAuthoritySimpleFactory(invoke, Constants.USPS_TOKEN_RUL);

        Assert.isTrue(ObjUtil.isAllNotEmpty(timeStamp, clientId,clientSecret,token_url), "请配置授权格式,例: {\"token_url\":\"\",\"grant_type\":\"\",\"client_id\":\"\",\"client_secret\":\"\"}");
        JSONObject paramsAuth = new JSONObject();
        paramsAuth.put(Constants.USPS_CLIENT_ID, clientId);
        paramsAuth.put(Constants.USPS_CLIENT_SECRET, clientSecret);
        paramsAuth.put(Constants.USPS_GRANT_TYPE, grantType);
        try {
            OkHttpClient client = new OkHttpClient().newBuilder()
                    .build();
            MediaType mediaType = MediaType.parse("application/json");
            RequestBody body = RequestBody.create(mediaType, paramsAuth.toString());
            Request request = new Request.Builder()
                    .url(token_url)
                    .method("POST", body)
                    .addHeader("Content-Type", "application/json")
                    //.addHeader("Cookie", "cookie")  //自带token ???
                    .build();
            Response response = client.newCall(request).execute();
            String bodys = response.body().string();
            JSONObject  json= JSONObject.parseObject(bodys);
            return  json;
        }catch (Exception e){

        }
        //项目启动第一次成功 后面全部失败？？？？
        HttpHeaders httpHeaders = new HttpHeaders();
        HttpMethod requestMethod = common.convertRequestMethod("POST");
        Object res = getBaseAspect(invoke.getAppName()).httpRequest(token_url, requestMethod, paramsAuth, httpHeaders,String.class, Constants.Read,StrUtil.EMPTY);
        JSONObject  json= JSONObject.parseObject(res.toString());
         return  json;
        //        //调用接口获取access-token
//        Object accessTokenResult;
//        String accessToken = null;
//        if (HttpUtil.isHttp(tokenUrl) || HttpUtil.isHttps(tokenUrl)) {
//            accessTokenResult = restUtilLingXing.lingXingRequest("1", "post", paramsAuth, tokenUrl, null, null);
//            JSONObject jsonObject = (JSONObject) accessTokenResult;
//            if (!"200".equals(jsonObject.get("code"))) {
//                Assert.isTrue(false, "应用 {} 获取AccessToken失败，错误信息 {}", invoke.getAppName(), jsonObject.get("msg"));
//            }
//            //取得access-token
//            accessToken = ((JSONObject) jsonObject.get("data")).get("access_token").toString();
//        } else {
//            Assert.isTrue(false, "应用 {} 请求路径 {} 错误，请检查配置", invoke.getAppName(), tokenUrl);
//        }
//        return accessToken;
    }


    @Override
    public Object invoke(DataContextModel.DatainterfaceInvokeModel invoke, Object currentParamsMap, JSONObject currentHeadersMap) {
        HttpHeaders httpHeaders = new HttpHeaders();
        // 请求地址
        String path =  URLUtil.toUrlForHttp(StrUtil.concat(true,invoke.getAuthority().getRootPath(),invoke.getInterfaceUrl())).toString();
        // 请求方法
        HttpMethod requestMethod = common.convertRequestMethod(invoke.getRequestMethod());
        if (HttpUtil.isHttp(path) || HttpUtil.isHttps(path)) {
            if (!StrUtil.equalsIgnoreCase(RequestMethodKind.Get.getValue(), requestMethod.name())
                    &&!StrUtil.equalsIgnoreCase(RequestMethodKind.Post.getValue(), requestMethod.name())
                    &&!StrUtil.equalsIgnoreCase(RequestMethodKind.Delete.getValue(), requestMethod.name())
                    &&!StrUtil.equalsIgnoreCase(RequestMethodKind.Put.getValue(), requestMethod.name())) {
                Assert.isTrue(false, "接口 {} ，指定的查询类型 {} 错误 ！",  invoke.getEnCode(), requestMethod.name());
            }
            Object res;
            try {
                JSONObject jsonObject = getAuth(invoke.getAuthority());
                httpHeaders.add("Authorization",jsonObject.getString("token_type")+" "+jsonObject.getString("access_token"));
                JSONObject jsonObject1=  JSONObject.parseObject(currentParamsMap.toString());
                if(currentParamsMap!=null&&StringUtils.hasText(jsonObject1.getString("trackingNumber"))){
                    //path=path+jsonObject1.getString("trackingNumber");
                    path= String.format(path,jsonObject1.getString("trackingNumber"));
                    jsonObject1.remove("trackingNumber");
                }
                if(currentParamsMap!=null&&StringUtils.hasText(jsonObject1.getString("If-Match"))){
                    httpHeaders.add("If-Match",jsonObject1.getString("If-Match"));
                    jsonObject1.remove("If-Match");
                }
                res = getBaseAspect(invoke.getAuthority().getAppName()).httpRequest(path, requestMethod, jsonObject1, httpHeaders,String.class, Constants.Read,StrUtil.EMPTY);
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new RuntimeException(StrUtil.format("API 接口 {} ，执行 {} 操作 {} 发生异常 ",  invoke.getEnCode(), path, StrUtil.subPre(JsonUtil.getObjectToString(currentParamsMap), 500), ExceptionUtil.getRootCauseMessage(ex)));
            }
            if (ObjectUtil.isEmpty(res)) {
                throw new RuntimeException(StrUtil.concat(true, "拉取失败或无返回值：", StrUtil.subPre(JsonUtil.getObjectToString(res), 500)));
            }
            return jScriptUtil.callJsInvoke(invoke.getDataProcessing(), res == null ? new ArrayList<>() : res, null, null);
        } else {
            Assert.isTrue(false, "接口 {} ，地址 {} 错误 ！", invoke.getEnCode(), path);
        }
        return null;
    }
}
